/** @file    LayoutStandard.cpp
 *  @author  Alessandro Polo
 *  @version $Id: LayoutStandard.cpp 2258 2010-04-02 13:02:21Z alex $
 *  @brief
 * File containing methods for the wosh::gui::LayoutStandard class.
 * The header for this class can be found in LayoutStandard.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include "LayoutStandard.h"

 #include <QtGui>


using namespace std;
namespace wosh {
 namespace gui {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////// GadgetsContainer

GadgetsContainer::GadgetsContainer() : QGraphicsWidget()
 {
	this->layout = new QGraphicsLinearLayout(this);
	this->layout->setSpacing(0.0);
	this->layout->setContentsMargins(0,0,0,0);
	this->layout->setOrientation(Qt::Vertical);

	setLayout(this->layout);
	setFlag(QGraphicsItem::ItemIsMovable,false);
	setFlag(QGraphicsItem::ItemIsFocusable,true);
	setFlag(QGraphicsItem::ItemIsSelectable,true);
 }

void GadgetsContainer::addGadget( QGraphicsWidget* item )
 {
	item->setParentItem(this);
	item->setMaximumWidth(this->geometry().width());
	this->layout->addItem(item);
 }

//////////////////////////////////////////////////////////////////////////////////////////// GadgetsContainer
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////// LayerModalProxy

LayerModalProxy::LayerModalProxy() : QGraphicsProxyWidget()
 {
	setZValue(2000);
#if QT_VERSION >= 0x040600
	setPanelModality( QGraphicsItem::SceneModal );
	setGraphicsEffect( new QGraphicsDropShadowEffect() );
#endif
 }

void LayerModalProxy::configureFor( QWidget* widget )
 {
	if ( this->scene() == NULL ) {
		setWidget(widget);
		return;
	 }
	if ( widget == NULL ) {
#if QT_VERSION >= 0x040600
		setPanelModality( QGraphicsItem::NonModal );

		QPropertyAnimation* animation = new QPropertyAnimation(this, "geometry");
		animation->setDuration(500);
		animation->setStartValue( QRectF( this->scene()->sceneRect().center() - this->rect().center(), this->size() ) );
		animation->setEndValue( QRectF( this->scene()->sceneRect().center(), QSize(0,0) ) );
		animation->setEasingCurve(QEasingCurve::InCirc );
		animation->start();
#endif
		setWidget(NULL);
	 }
	else {
		setWidget(widget);

#if QT_VERSION >= 0x040600
		setPos( this->scene()->sceneRect().center() - this->rect().center() );
		setZValue(2000);
		setPanelModality( QGraphicsItem::SceneModal );

		QPropertyAnimation* animation = new QPropertyAnimation(this, "geometry");
		animation->setDuration(500);
		animation->setStartValue( QRectF( this->scene()->sceneRect().center(), QSize(0,0) ) );
		animation->setEndValue( QRectF( this->scene()->sceneRect().center() - this->rect().center(), this->size() ) );
		animation->setEasingCurve(QEasingCurve::InCirc );
		animation->start();
#endif
	 }
 }

///////////////////////////////////////////////////////////////////////////////////////////// LayerModalProxy
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////// LayerOpaque

LayerOpaque::LayerOpaque() : QGraphicsRectItem()
 {
	setZValue(2000);
	setVisible(false);
	setEnabled(true);

	// appearance
	setBrush( QBrush(QColor(18, 18, 18, 210)) );


#if QT_VERSION >= 0x040600
	setOpacity(0.0);
#endif
 }

void LayerOpaque::init() {
	// intercept any input and deny input to propagate behind me
	setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MidButton | Qt::XButton1 | Qt::XButton2);
	setFlag(QGraphicsItem::ItemIsMovable,false);
	setFlag(QGraphicsItem::ItemIgnoresTransformations,true);

#if QT_VERSION >= 0x040600
	setAcceptTouchEvents(true);
	setFlag(QGraphicsItem::ItemDoesntPropagateOpacityToChildren,true);
	setFlag(QGraphicsItem::ItemIgnoresParentOpacity,true);
	setFlag(QGraphicsItem::ItemAcceptsInputMethod,true);
#endif
 }

void LayerOpaque::showLayer( bool visible, bool opaque_n_animation )
 {
	if ( visible ) {
		setFocus();
	 }
	else {
		clearFocus();
	 }

	if ( !opaque_n_animation ) {
		setVisible(visible);
#if QT_VERSION >= 0x040600
		setOpacity(0.0);
#endif
		return;
	 }

	if ( visible ) {
		grabKeyboard();
		grabMouse();
		grabKeyboard();
		grabMouse();
	 }

#if QT_VERSION >= 0x040600
	QPropertyAnimation* animation = new QPropertyAnimation(this, "opacity");
	animation->setDuration(1000);
	animation->setEasingCurve(QEasingCurve::OutCubic); // OutBounce
	if ( visible ) {
		animation->setStartValue( 0.0 );
		animation->setEndValue( 1.0 );
	 }
	else {
		animation->setStartValue( 1.0 );
		animation->setEndValue( 0.0 );
	 }
	animation->start();
#endif
	setVisible(visible);
 }

///////////////////////////////////////////////////////////////////////////////////////////////// LayerOpaque
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////// LayoutStandard

LayoutStandard::LayoutStandard() : QObject(), KioskLayout()
 {
	this->navigatorHeight = 110;
	this->gadgetWidth= 200;

	this->scene = NULL;
	this->sheetCurrent = NULL;
	this->navigator = NULL;
	this->gadgetsContainer = NULL;
	this->itemLayerOpaque = NULL;
	this->itemModalProxy = NULL;

	this->navListener = NULL;

	init();
 }

void LayoutStandard::init()
 {
	this->scene = new QGraphicsScene( QRectF(0,0,800,600) );
	this->scene->setBackgroundBrush( Qt::black );

	////////////////////////////////////////////// navigator
	this->navigator = new Navigator();
	this->navigator->setRect( this->scene->sceneRect().adjusted(0,this->scene->sceneRect().height()-navigatorHeight,0,0) );
	this->navigator->setZValue(1000);
	this->scene->addItem(this->navigator);
	this->navigator->setupButtons();
	connect(this->navigator, SIGNAL(itemSelected(NavigatorItem*)), this, SLOT(navigator_itemSelected(NavigatorItem*)));

	////////////////////////////////////////////// gadgets
	this->gadgetsContainer = new GadgetsContainer();
	this->gadgetsContainer->setGeometry( this->scene->sceneRect().adjusted(this->scene->sceneRect().width()-gadgetWidth,0,0,-navigatorHeight) );
	this->gadgetsContainer->setZValue(900);
	this->gadgetsContainer->setMaximumWidth(gadgetWidth);
	this->scene->addItem(this->gadgetsContainer);

	////////////////////////////////////////////// opaque layer
	this->itemLayerOpaque = new LayerOpaque();
	this->itemLayerOpaque->setRect( this->scene->sceneRect().adjusted(-100,-100,+100,+100) ); // overflow
	this->scene->addItem(this->itemLayerOpaque);
	this->itemLayerOpaque->init();

	////////////////////////////////////////////// modal panel
	this->itemModalProxy = new LayerModalProxy();
	this->itemModalProxy->setParentItem(this->itemLayerOpaque);
 }

void LayoutStandard::showModal( QWidget* panel ) {
	this->itemModalProxy->configureFor(panel);
	this->itemLayerOpaque->showLayer(true);
 }

void LayoutStandard::hideModal() {
	this->itemModalProxy->configureFor(NULL);
	this->itemLayerOpaque->showLayer(false);
 }

void LayoutStandard::maximize_sheet( bool value )
 {
	if ( this->sheetCurrent == NULL )
		return;
	if ( value ) {
		this->sheetCurrent->setGeometry( this->scene->sceneRect() );
		this->sheetCurrent->setZValue(10000);
	 }
	else {
		this->sheetCurrent->setGeometry( this->scene->sceneRect().adjusted(0,0,-this->gadgetWidth,-this->navigatorHeight) );
		this->sheetCurrent->setZValue(800);
	 }
 }

bool LayoutStandard::maximize( QGraphicsWidget* item )
 {
	item->setGeometry( this->scene->sceneRect() );
	item->setZValue(10000);
	return true;
 }

void LayoutStandard::setSheet( QGraphicsWidget* item )
 {
	if ( this->sheetCurrent != NULL ) {
		this->scene->removeItem(this->sheetCurrent);
	 }
	this->sheetCurrent = item;
	this->sheetCurrent->setGeometry( this->scene->sceneRect().adjusted(0,0,-this->gadgetWidth,-this->navigatorHeight) );
	this->sheetCurrent->setZValue(800);
	this->sheetCurrent->setFlag(QGraphicsItem::ItemIsMovable,false);
	this->sheetCurrent->setFlag(QGraphicsItem::ItemIsFocusable,true);
	this->sheetCurrent->setFlag(QGraphicsItem::ItemIsSelectable,true);
	this->scene->addItem(this->sheetCurrent);
 }

void LayoutStandard::addGadget( QGraphicsWidget* item )
 {
	this->gadgetsContainer->addGadget( item );
 }

void LayoutStandard::blockInput( bool add_opaque_layer )
 {
	this->itemLayerOpaque->showLayer(true, add_opaque_layer);
 }


void LayoutStandard::setNavigatorListener( INavigatorListener* listener ) {
	this->navListener = listener;
 }

void LayoutStandard::navigator_itemSelected( NavigatorItem* item ) {
	if ( this->navListener != NULL )
		this->navListener->itemSelected(item);
}


////////////////////////////////////////////////////////////////////////////////////////////// LayoutStandard
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////


  }; // namespace gui
}; // namespace wosh

